//
// Created by busted on 2022/7/31.
//

#include <catch2/catch.hpp>
#include <libdag/source.hpp>
#include <libdag/channel.hpp>
#include <libdag/sink.hpp>
#include <iostream>

class step : public libdag::source {
public:
    step() : source(1)
    {}

    void run(libdag::runnable_context &) override
    {
        std::byte bytes[] = {std::byte{1}, std::byte{2}, std::byte{3}};
        output(0)->write(bytes, sizeof(bytes));
    }

    bool is_ready() const noexcept override
    {
        return output(0) != nullptr;
    }
};

std::ostream& operator<< (std::ostream& os, std::byte b) {
    return os << std::to_integer<int>(b);
}

class obsv : public libdag::sink {
public:
    obsv() : sink(1)
    {}

    void run(libdag::runnable_context &) override
    {
        std::byte bytes[3];
        input(0)->read(bytes, sizeof(bytes));
        std::cout << bytes[0] << bytes[1] << bytes[2] << std::endl;
    }

    bool is_ready() const noexcept override
    {
        return input(0)->bytes_available() > 0;
    }
};

TEST_CASE("test.dag.channel")
{
    libdag::channel channel;
    step s;
    obsv o;
    libdag::connect(&channel, &s, 0, &o, 0);
    libdag::runnable_context ctx;

    REQUIRE(!o.is_ready());
    REQUIRE(s.is_ready());
    for (auto i = 0; i < 100; ++i) {
        s.run(ctx);
        o.run(ctx);
    }
}
